package com.iszhangsc.backup.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Validator;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.iszhangsc.backup.common.ResultVO;
import com.iszhangsc.backup.model.BackupRecord;
import com.iszhangsc.backup.param.dto.ReductionDTO;
import com.iszhangsc.backup.param.vo.DatabaseTableVO;
import com.iszhangsc.backup.scheduled.DatabaseBackupScheduled;
import com.iszhangsc.backup.service.DatabaseBackupService;
import com.iszhangsc.backup.util.CronUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 数据备份
 * </p>
 *
 * @author zhāngshìchāng
 * @date 2020/12/8 3:03 下午
 */
@RestController
@Api(tags = {"数据备份"})
@RequestMapping("/database")
public class BackupRecordController {

    private final DatabaseBackupService databaseBackupService;
    private final DatabaseBackupScheduled dataBackupScheduled;

    public BackupRecordController(DatabaseBackupService databaseBackupService, DatabaseBackupScheduled dataBackupScheduled) {
        this.databaseBackupService = databaseBackupService;
        this.dataBackupScheduled = dataBackupScheduled;
    }


    @GetMapping("/page")
    @ApiOperation("备份分页列表")
    @ApiOperationSupport(order = 1)
    public ResultVO<Page<BackupRecord>> page(Integer pageNum, Integer pageSize) {
        Page<BackupRecord> page = databaseBackupService.page(pageNum, pageSize);
        return ResultVO.ok(page);
    }


    @GetMapping("/nextExecTime")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "CRON表达式最近执行时间", notes = "通过CRON表达式获取最近执行时间")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "cronExpression", value = "CRON表达式", example = "0 0 0 * 1/3 ? *", required = true),
            @ApiImplicitParam(name = "n", value = "展示n次执行结果", example = "5", defaultValue = "5"),
    })
    public ResultVO<List<Date>> nextExecTime(@RequestParam String cronExpression,
                                             @RequestParam(required = false, defaultValue = "5") Integer n) {
        return ResultVO.ok(CronUtils.nextExecTime(cronExpression, n));
    }


    @PostMapping("/updateExecTime")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "更新备份定时任务时间", notes = "更新备份定时任务时间")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "cronExpression", value = "CRON表达式", example = "0/1 * * * * ?", required = true),
    })
    public ResultVO<?> updateExecTime(@RequestParam String cronExpression) {
        Validator.validateTrue(CronUtils.isValidExpression(cronExpression), "CRON表达式错误");
        dataBackupScheduled.resetTriggerTask(cronExpression);
        return ResultVO.ok();
    }


    @PostMapping("/backup")
    @ApiOperationSupport(order = 10)
    @ApiOperation(value = "备份数据")
    public ResultVO<?> backup() {
        return databaseBackupService.doBackup() ? ResultVO.ok() : ResultVO.fail("备份失败");
    }


    @GetMapping("/tables")
    @ApiOperationSupport(order = 20)
    @ApiOperation(value = "需要还原的数据库表展示")
    public ResultVO<List<DatabaseTableVO>> tables() {
        return ResultVO.ok(databaseBackupService.tables(null));
    }


    @PostMapping("/reduction")
    @ApiOperationSupport(order = 21)
    @ApiOperation(value = "还原备份数据")
    public ResultVO<?> reduction(@Valid @RequestBody ReductionDTO dto) {
        Validator.validateTrue(FileUtil.isFile(dto.getPath()), "备份文件不存在,无法进行还原");
        return databaseBackupService.doReduction(dto) ? ResultVO.ok() : ResultVO.fail("备份还原失败");
    }


}
